from typing import Literal, List, Dict, Any, Union, Tuple
from audio_pkg.utils.get_token import GetAccessToken
from audio_pkg.core.handler.status_handler import TaskFileHandler
import requests
import json
#创建语音任务
class CreateAudioTask:
    def __init__(
            self,
            api_url:str,
            logger,  # 用于记录日志的对象
            gettoken: GetAccessToken,  # 获取访问令牌的对象
            file_handler: TaskFileHandler,  # 处理任务文件的对象
            text: str = None,  # 要转换为音频的文本
            language="zh",  # 设置语言，默认为中文
            speed: int = 5,  # 设置语速，默认为5
            volume: int = 5,  # 设置音量，默认为5
            voice: Literal[0, 1, 3, 4, 5003, 5118, 106] = 3,  # 选择语音的类型，默认为3
            pitch: int = 5,  # 设置音调，默认为5
            format: Literal["mp3-16k", "mp3-48k", "wav", "pcm-8k", "pcm-16k"] = "mp3-16k",  # 设置音频格式，默认为mp3-16k
            enable_subtitle: Literal[0, 1, 2] = 0  # 是否启用字幕，默认为0
    ):
        # 初始化参数
        self.api_url=api_url
        self.logger = logger  # 保存日志对象
        self.task_format = format  # 保存音频格式
        self.gettoken = gettoken  # 保存token获取对象
        self.file_handler = file_handler  # 保存文件处理对象
        

        # 创建请求体，包含要转换的文本、语言、语速、音量等参数
        self.body = {
            "text": text,  # 要转换的文本内容
            "lang": language,  # 语言
            "speed": speed,  # 语速
            "volume": volume,  # 音量
            "pitch": pitch,  # 音高
            "voice": voice,  # 语音类型
            "format": self.task_format,  # 音频格式
            "enable_subtitle": enable_subtitle  # 是否启用字幕
        }

        # 将请求体转换为JSON格式
        self.payload = json.dumps(self.body, ensure_ascii=False)

        # 请求头，指定内容类型和接受类型
        self.headers = {
            'Content-Type': 'application/json',  # 内容类型为JSON
            'Accept': 'application/json'  # 接受的响应类型为JSON
        }

        # 请求参数，包含access_token（访问令牌）
        self.params = {
            "access_token": self.gettoken.back_token()  # 获取并返回获取的令牌
        }

        # 初始化任务ID和响应对象
        self.task_id = None  # 任务ID初始化为None
        self.response = None  # 响应初始化为None

    def create_task(self):
        """
        创建音频转换任务，发送POST请求到服务端。
        - 请求服务端创建任务并获取响应
        - 如果成功，获取返回的任务ID并保存
        - 若任务创建失败，记录错误日志
        - 成功时，将返回的任务数据追加到文件中
        """
        try:
            # 发送POST请求，创建音频任务
            self.response = requests.post(
                url = self.api_url,  # 服务端创建任务的URL
                headers=self.headers,  # 请求头
                data=self.payload.encode('utf-8'),  # 请求体（数据内容）
                params=self.params  # 请求参数（如token）
            )

            # 如果返回的响应状态码不是2xx，抛出异常
            self.response.raise_for_status()

            # 获取返回的任务ID
            self.task_id = self.response.json().get("task_id")
            if not self.task_id:
                # 如果没有返回任务ID，说明任务创建失败
                raise ValueError("未能创建任务，请检查参数问题")

            # 记录任务创建成功的日志
            self.logger.info("返回数据：{}".format(self.response.json()))

            # 将返回的任务数据追加到文件中
            self.file_handler.handle(self.response.json(), self.task_format)
        except requests.RequestException as e:
            # 如果请求过程中发生异常，记录错误日志
            self.logger.error(f"创建任务失败：{e}")

    def back_task_info(self):
        """
        获取任务信息。
        - 如果任务ID无效，则抛出异常
        - 返回当前任务的ID
        """
        if not self.task_id:
            # 如果task_id没有被设置，说明任务未成功创建，抛出异常
            raise ValueError("任务id无效，请重新请求")
        return self.task_id  # 返回任务ID






#查询语音任务
class QueryTask:
    def __init__(
        self,
        api_ur: str,
        logger,  # 用于记录日志的对象
        gettoken: GetAccessToken  # 获取访问令牌的对象
    ):
        # 初始化参数
        self.api_url = api_ur #查询任务的api接口
        self.logger = logger  # 保存日志对象
        self._response: List[Dict[str, Any]] = []  # 初始化任务响应数据，类型为列表
        self._gettoken = gettoken  # 保存获取token对象
        self._headers = {
            'Content-Type': 'application/json',  # 设置请求内容类型为JSON
            'Accept': 'application/json'  # 设置响应接受类型为JSON
        }
        # 请求参数，包含access_token（访问令牌）
        self._params = {
            "access_token": self._gettoken.back_token()  # 获取并返回获取的令牌
        }
        self._task_ids: str | tuple = None  # 任务ID，支持单个ID或多个ID
        self._error_info: List[str] = []  # 初始化错误信息的列表
        self._task_results = []  # 初始化任务结果

    def query_task(self, task_id: Union[Tuple[str], str]):
        """
        查询任务状态，向服务端发送请求以获取任务信息。
        - 处理任务ID的输入，可以是单个任务ID或多个任务ID（元组）
        - 发送请求并获取任务状态和相关信息
        - 处理返回的数据，将错误信息和有效任务信息分别保存
        
        参数:
        - task_id (str | Tuple[str]): 单个任务ID或多个任务ID的元组
        """
        # 如果task_id是元组，直接赋值给self._task_ids
        if isinstance(task_id, tuple):
            self._task_ids = task_id
        # 如果task_id是字符串，则将其转换为元组
        elif isinstance(task_id, str):
            self._task_ids = (task_id,)
        else:
            # 如果task_id既不是字符串也不是元组，抛出类型错误
            raise ValueError("数据类型错误，要求是字符串或者元组")

        # 创建请求体，包含任务ID列表
        payload = json.dumps({
            "task_ids": list(self._task_ids)  # 将任务ID列表转换为JSON格式
        }, ensure_ascii=False)

        # 向服务端发送POST请求，查询任务信息
        self.task_results = requests.post(
            url = self.api_url,  # 查询任务的API URL
            headers=self._headers,  # 请求头
            data=payload.encode('utf-8'),  # 请求体（数据内容）
            params=self._params  # 请求参数（如access_token）
        )

        # 获取并保存错误信息，如果有的话
        self._error_info = self.task_results.json().get("error_info", [])

        # 获取并保存有效的任务信息，如果有的话
        self._response = self.task_results.json().get("tasks_info", [])

    def result(self):
        """
        返回查询任务的结果，包括错误信息和有效任务信息。
        
        返回:
        - error_info (List[str]): 错误信息列表
        - response (List[Dict[str, Any]]): 有效的任务信息列表
        """
        return self._error_info, self._response  # 返回错误信息和有效任务信息


        
    

